package com.yanqu.road.server.gameplayer.module.activity.wanyao;

import com.yanqu.road.entity.activity.ActivityConfig;
import com.yanqu.road.entity.activity.ActivityInfo;
import com.yanqu.road.entity.activity.args.WanYaoAddMonsterArgs;
import com.yanqu.road.entity.activity.wanyao.config.*;
import com.yanqu.road.entity.activity.wanyao.data.WanYaoUserData;
import com.yanqu.road.entity.activity.wanyao.entity.*;
import com.yanqu.road.entity.config.goods.GoodsInfo;
import com.yanqu.road.entity.enums.activity.wanyao.eWanYaoTalentBuffType;
import com.yanqu.road.entity.enums.eGamePlayerEventType;
import com.yanqu.road.entity.enums.eLogMoneyType;
import com.yanqu.road.entity.enums.eSystemId;
import com.yanqu.road.entity.log.wanyao.LogWanYaoActiveTalent;
import com.yanqu.road.entity.log.wanyao.LogWanYaoGoOut;
import com.yanqu.road.entity.log.wanyao.LogWanYaoOperateBlock;
import com.yanqu.road.logic.bussiness.activity.WanYaoBusiness;
import com.yanqu.road.logic.helper.CalcPowerResult;
import com.yanqu.road.logic.helper.PowerHelper;
import com.yanqu.road.pb.activity.WanYaoProto;
import com.yanqu.road.server.gameplayer.GamePlayer;
import com.yanqu.road.server.gameplayer.module.activity.ActivityModule;
import com.yanqu.road.server.gameplayer.module.base.GeneralModule;
import com.yanqu.road.server.gameplayer.module.player.CurrencyModule;
import com.yanqu.road.server.logic.activity.BaseActivityData;
import com.yanqu.road.server.logic.activity.condition.BaseActivityCondition;
import com.yanqu.road.server.manger.activity.ActivityMgr;
import com.yanqu.road.server.manger.activity.NormalActivityMgr;
import com.yanqu.road.server.manger.activity.wanyao.WanYaoMgr;
import com.yanqu.road.server.manger.config.GoodsMgr;
import com.yanqu.road.server.manger.config.SystemOpenMgr;
import com.yanqu.road.server.manger.log.AutoLogMgr;
import com.yanqu.road.server.protocol.ClientProtocol;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.utils.property.Property;
import com.yanqu.road.utils.property.PropertyHelper;
import com.yanqu.road.utils.string.StringUtils;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

import static com.yanqu.road.server.manger.activity.wanyao.WanYaoMgr.getInitBoardData;
import static com.yanqu.road.server.manger.activity.wanyao.WanYaoMgr.getWanYaoMonsterKingConfigByLevel;

public class WanYaoModule extends GeneralModule {

    private WanYaoUserData userData;

    private static int MAX_LEVEL = 20;

    @Override
    public void afterLogin() {
        syncConfig();
        syncUserData();
    }

    public WanYaoModule(GamePlayer player) {
        super(player);
    }

    @Override
    public boolean loadData() {
        ActivityInfo activityInfo = WanYaoMgr.getActivityInfo();
        if (activityInfo == null){
            return true;
        }
        userData = WanYaoBusiness.getWanYaoUserData(activityInfo.getActivityId(),getUserId());
        if (userData == null){
            if (SystemOpenMgr.systemOpen(player,eSystemId.WanYao.getValue())){
                initUserData();
            }
        }
        return true;

    }

    @Override
    public boolean afterLoadData() {
        return true;
    }

    @Override
    public boolean saveData() {
        if (userData != null){
            if (userData.isInsertOption()){
                WanYaoBusiness.addWanYaoUserData(userData);
            }else if (userData.isUpdateOption()){
                WanYaoBusiness.updateWanYaoUserData(userData);
            }
        }
        return true;
    }

    /**
     * 引导
     */
    public int guide(int activityId, int step){
        int check = simpleCheck(activityId);
        if (check != 0){
            return check;
        }

        int operateType = 0;

        WanYaoBlockData copyBlockData = null;

        WanYaoConfig config = WanYaoMgr.getConfig();
        if (step == 1){
            List<Integer> guideClick1 = config.getGuideClick1();
            WanYaoBlockData blockByXY = getBlockByXY(userData.getNowBoardData(), guideClick1.get(0), guideClick1.get(1));
            if (blockByXY == null){
                return GameErrorCode.E_WAN_YAO_ACTIVITY_CONFIG_ERROR;
            }
            copyBlockData = blockByXY.copy();
            List<WanYaoProto.WanYaoMergeParseMsg> allMergeParse = new ArrayList<>();
            //玩家的第一次操作记录
            WanYaoProto.WanYaoMergeParseMsg.Builder userOperateMsg = WanYaoProto.WanYaoMergeParseMsg.newBuilder();
            userOperateMsg.setOldBoard(parseBoardMsg(userData.getNowBoardData()));

            int oldId = blockByXY.getBlockId();
            int oldLevel = blockByXY.getBlockLevel();

            blockByXY.setBlockLevel(0);

            //第一次上阵记录
            WanYaoProto.WanYaoSingleMergeMsg.Builder singleMergeMsg = WanYaoProto.WanYaoSingleMergeMsg.newBuilder();
            singleMergeMsg.setNewBlock(parseBlockMsg(blockByXY));

            WanYaoProto.MonsterData.Builder monsterData = WanYaoProto.MonsterData.newBuilder();
            monsterData.setMonsterId(oldLevel);
            monsterData.setMonsterNum(1);
            singleMergeMsg.addNewMonster(monsterData);
            addMonster(oldLevel, 1);

            reCalculateMonsterPower();
            singleMergeMsg.setNewMonsterPower(userData.getMonsterPower());

            userOperateMsg.addSingleMerge(singleMergeMsg);

            userOperateMsg.setNewBoard(parseBoardMsg(userData.getNowBoardData()));
            allMergeParse.add(userOperateMsg.build());

            //掉落
            WanYaoProto.WanYaoMergeParseMsg.Builder fallMsg = WanYaoProto.WanYaoMergeParseMsg.newBuilder();
            fallMsg.setOldBoard(parseBoardMsg(userData.getNowBoardData()));
            userData.setNowBoardData(getInitBoardData(1));

            fallMsg.setNewBoard(parseBoardMsg(userData.getNowBoardData()));
            allMergeParse.add(fallMsg.build());


            userData.setGuideStep(1);

            WanYaoProto.OperateWanYaoBoardResp.Builder resp = WanYaoProto.OperateWanYaoBoardResp.newBuilder();
            resp.setRet(0);
            //第一步上阵
            operateType = 2;
            resp.setOperateType(operateType);
            resp.setId(oldId);
            resp.addAllMergeParse(allMergeParse);
            resp.setUserData(parseUserBuilder());
            player.notifyListener(eGamePlayerEventType.WanYaoUserPowerRank.getValue(),userData.getMonsterPower());
            player.sendPacket(ClientProtocol.U_WAN_YAO_OPERATE_BOARD, resp);


        }else if (step == 2){
            List<Integer> guideClick2 = config.getGuideClick2();
            WanYaoBlockData blockByXY = getBlockByXY(userData.getNowBoardData(), guideClick2.get(0), guideClick2.get(1));
            if (blockByXY == null){
                return GameErrorCode.E_WAN_YAO_ACTIVITY_CONFIG_ERROR;
            }
            copyBlockData = blockByXY.copy();
            List<WanYaoProto.WanYaoMergeParseMsg> allMergeParse = new ArrayList<>();
            //玩家的第一次操作记录
            WanYaoProto.WanYaoMergeParseMsg.Builder userOperateMsg = WanYaoProto.WanYaoMergeParseMsg.newBuilder();
            userOperateMsg.setOldBoard(parseBoardMsg(userData.getNowBoardData()));

            int oldId = blockByXY.getBlockId();
            int oldLevel = blockByXY.getBlockLevel();

            blockByXY.setBlockLevel(blockByXY.getBlockLevel()+1);

            //玩家操作
            WanYaoProto.WanYaoSingleMergeMsg.Builder singleMergeMsg = WanYaoProto.WanYaoSingleMergeMsg.newBuilder();
            singleMergeMsg.setNewBlock(parseBlockMsg(blockByXY));
            singleMergeMsg.setNewMonsterPower(userData.getMonsterPower());

            userOperateMsg.addSingleMerge(singleMergeMsg);
            userOperateMsg.setNewBoard(parseBoardMsg(userData.getNowBoardData()));

            allMergeParse.add(userOperateMsg.build());

            WanYaoProto.WanYaoMergeParseMsg.Builder builder = checkMerge(userData.getNowBoardData(), blockByXY);
            allMergeParse.add(builder.build());

            WanYaoProto.WanYaoMergeParseMsg.Builder firstFallMsg = WanYaoProto.WanYaoMergeParseMsg.newBuilder();
            firstFallMsg.setOldBoard(parseBoardMsg(userData.getNowBoardData()));
            userData.setNowBoardData(WanYaoMgr.getInitBoardData(2));
            firstFallMsg.setNewBoard(parseBoardMsg(userData.getNowBoardData()));
            allMergeParse.add(firstFallMsg.build());

            WanYaoProto.WanYaoMergeParseMsg.Builder secondMerge = checkMerge(userData.getNowBoardData(), null);
            allMergeParse.add(secondMerge.build());

            WanYaoProto.WanYaoMergeParseMsg.Builder secondFallMsg = WanYaoProto.WanYaoMergeParseMsg.newBuilder();
            secondFallMsg.setOldBoard(parseBoardMsg(userData.getNowBoardData()));
            userData.setNowBoardData(WanYaoMgr.getInitBoardData(3));
            secondFallMsg.setNewBoard(parseBoardMsg(userData.getNowBoardData()));
            allMergeParse.add(secondFallMsg.build());

            WanYaoProto.WanYaoMergeParseMsg.Builder thirdMerge = checkMerge(userData.getNowBoardData(), null);
            allMergeParse.add(thirdMerge.build());

            WanYaoProto.WanYaoMergeParseMsg.Builder thirdFallMsg = WanYaoProto.WanYaoMergeParseMsg.newBuilder();
            thirdFallMsg.setOldBoard(parseBoardMsg(userData.getNowBoardData()));
            userData.setNowBoardData(WanYaoMgr.getInitBoardData(4));
            thirdFallMsg.setNewBoard(parseBoardMsg(userData.getNowBoardData()));
            allMergeParse.add(thirdFallMsg.build());

            WanYaoProto.WanYaoMergeParseMsg.Builder fourthMerge = checkMerge(userData.getNowBoardData(), null);
            allMergeParse.add(fourthMerge.build());

            WanYaoProto.WanYaoMergeParseMsg.Builder fourFallMsg = WanYaoProto.WanYaoMergeParseMsg.newBuilder();
            fourFallMsg.setOldBoard(parseBoardMsg(userData.getNowBoardData()));
            userData.setNowBoardData(WanYaoMgr.getInitBoardData(5));
            fourFallMsg.setNewBoard(parseBoardMsg(userData.getNowBoardData()));
            allMergeParse.add(fourFallMsg.build());


            userData.setGuideStep(2);

            WanYaoProto.OperateWanYaoBoardResp.Builder resp = WanYaoProto.OperateWanYaoBoardResp.newBuilder();
            resp.setRet(0);
            //第一步上阵
            operateType = 1;
            resp.setOperateType(operateType);
            resp.setId(oldId);
            resp.addAllMergeParse(allMergeParse);
            resp.setUserData(parseUserBuilder());
            player.notifyListener(eGamePlayerEventType.WanYaoUserPowerRank.getValue(),userData.getMonsterPower());
            player.sendPacket(ClientProtocol.U_WAN_YAO_OPERATE_BOARD, resp);

        }
        LogWanYaoOperateBlock log = new LogWanYaoOperateBlock(activityId,
                getUserId(),
                operateType,
                copyBlockData,
                new ArrayList<>(),
                new HashMap<>(),
                new HashMap<>(),
                new HashMap<>(),
                new HashMap<>(),
                userData.getMonsterKingLevel(),
                0,
                userData.getMonsterPower(),
                userData.getSteps(),
                new Date()
        );
        AutoLogMgr.add(log);

        return 0;
    }







    /**
     * 检测惊魂花增加 返回level
     */
    public int checkTriggerAddExp() {
        WanYaoBuffData buffData = userData.getBuffDataMap().get(eWanYaoTalentBuffType.extraExpReward.getValue());
        if (buffData == null) {
            return 0;
        }
        if (buffData.getBuffId() <= 0) {
            return 0;
        }
        if (buffData.getBuffTime() <= 0) {
            return 0;
        } else {
            WanYaoTalentConfig configById = WanYaoMgr.getWanYaoTalentConfigById(buffData.getBuffId());//获取buff配置
            if (configById == null) {
                log.error("wan yao activity operate talent buff config error activityId:{} buffId:{}", userData.getActivityId(), buffData.getBuffId());
                return 0;
            }
            List<Integer> talentParaList = configById.getTalentParaList();

            if (talentParaList.size() != 2) {
                log.info("wan yao activity add step talent buff config error activityId:{} buffId:{} talentParaList:{}", userData.getActivityId(), buffData.getBuffId(), talentParaList);
                return 0;
            }

            return configById.getLevel();
        }
    }


    /**
     * 检测妖力增加触发 返回level
     */
    public int checkTriggerAddMonsterPower() {
        WanYaoBuffData buffData = userData.getBuffDataMap().get(eWanYaoTalentBuffType.addAllMonsterPower.getValue());
        if (buffData == null) {
            return 0;
        }
        if (buffData.getBuffId() <= 0) {
            return 0;
        }
        if (buffData.getBuffTime() <= 0) {
            return 0;
        } else {
            WanYaoTalentConfig configById = WanYaoMgr.getWanYaoTalentConfigById(buffData.getBuffId());//获取buff配置
            if (configById == null) {
                log.info("wan yao activity operate talent buff config error activityId:{} buffId:{}", userData.getActivityId(), buffData.getBuffId());
                return 0;
            }
            List<Integer> talentParaList = configById.getTalentParaList();

            if (talentParaList.size() != 2) {
                log.info("wan yao activity add step talent buff config error activityId:{} buffId:{} talentParaList:{}", userData.getActivityId(), buffData.getBuffId(), talentParaList);
                return 0;
            }

            return configById.getLevel();
        }
    }


    /**
     * 检测增加怪物buff触发 返回level
     */
    public int checkTriggerTemporaryAddMonster(Map<Integer, WanYaoMonsterData> copyMap) {
        WanYaoBuffData buffData = userData.getBuffDataMap().get(eWanYaoTalentBuffType.addBattleMonster.getValue());
        if (buffData == null) {
            return 0;
        }
        if (buffData.getBuffId() <= 0) {
            return 0;
        }
        if (buffData.getBuffTime() <= 0) {
            return 0;
        } else {
            WanYaoTalentConfig configById = WanYaoMgr.getWanYaoTalentConfigById(buffData.getBuffId());//获取buff配置
            if (configById == null) {
                log.error("wan yao activity operate talent buff config error activityId:{} buffId:{}", userData.getActivityId(), buffData.getBuffId());
                return 0;
            }
            List<Integer> talentParaList = configById.getTalentParaList();

            if (talentParaList.size() != 3) {
                log.info("wan yao activity add step talent buff config error activityId:{} buffId:{} talentParaList:{}", userData.getActivityId(), buffData.getBuffId(), talentParaList);
                return 0;
            }


            int newLevel = talentParaList.get(2);
            int addNum = talentParaList.get(1);

            if (copyMap.containsKey(newLevel)) {
                //拿出旧数据
                WanYaoMonsterData oldData = copyMap.get(newLevel);
                //使用一个新的对象替换到这个copyMap里面
                WanYaoMonsterData monsterData = new WanYaoMonsterData();
                monsterData.setLevel(newLevel);
                monsterData.setMonsterNum(oldData.getMonsterNum() + addNum);
                copyMap.put(newLevel, monsterData);
            } else {
                WanYaoMonsterData monsterData = new WanYaoMonsterData();
                monsterData.setLevel(newLevel);
                monsterData.setMonsterNum(addNum);
                copyMap.put(newLevel, monsterData);
            }
            return configById.getLevel();

        }

    }


    /**
     * 检测是否触发增加步数buff 返回level
     */
    public int checkTriggerAddStepBuff() {
        if (userData.getHasAddStep()) {
            return 0;
        }
        WanYaoBuffData buffData = userData.getBuffDataMap().get(eWanYaoTalentBuffType.addStep.getValue());
        if (buffData == null) {
            return 0;
        }
        if (buffData.getBuffId() <= 0) {
            return 0;
        }
        if (buffData.getBuffTime() <= 0) {
            return 0;
        } else {                             //触发概率buff
            WanYaoTalentConfig configById = WanYaoMgr.getWanYaoTalentConfigById(buffData.getBuffId());//获取buff配置
            if (configById == null) {
                log.info("wan yao activity operate talent buff config error activityId:{} buffId:{}", userData.getActivityId(), buffData.getBuffId());
                return 0;
            }
            List<Integer> talentParaList = configById.getTalentParaList();

            if (talentParaList.size() != 2) {
                log.info("wan yao activity add step talent buff config error activityId:{} buffId:{} talentParaList:{}", userData.getActivityId(), buffData.getBuffId(), talentParaList);
                return 0;
            }
            buffData.setBuffTime(buffData.getBuffTime() - 1);

            int addStep = talentParaList.get(1);
            userData.setHasAddStep(true);
            userData.setSteps(userData.getSteps() + addStep);

            return configById.getLevel();
        }
    }

    /**
     * 检测触发的操作概率buff
     */
    public int checkTriggerOperateBuff() {
        WanYaoBuffData buffData = userData.getBuffDataMap().get(eWanYaoTalentBuffType.extraMonsterLevel.getValue());
        if (buffData == null) {
            return 0;
        }
        if (buffData.getBuffId() <= 0) {
            return 0;
        }
        if (buffData.getBuffTime() <= 0) {
            return 0;
        } else {                             //触发概率buff
            WanYaoTalentConfig configById = WanYaoMgr.getWanYaoTalentConfigById(buffData.getBuffId());//获取buff配置
            if (configById == null) {
                log.error("wan yao activity operate talent buff config error activityId:{} buffId:{}", userData.getActivityId(), buffData.getBuffId());
                return 0;
            }
            List<Integer> talentParaList = configById.getTalentParaList();
            if (talentParaList.size() != 3) {
                log.error("wan yao activity operate talent buff config error activityId:{} buffId:{}", userData.getActivityId(), buffData.getBuffId());
                return 0;
            }
            int rate = talentParaList.get(1);
            int random = new Random().nextInt(1000);
            if (random > rate) {
                return 0;
            }
            buffData.setBuffTime(buffData.getBuffTime() - 1);
            return buffData.getBuffId();
        }
    }

    /**
     * 激活天赋变成buff
     *
     * @param activityId
     * @param talentType
     * @param talentLevel
     * @return
     */

    public int activeTalent(int activityId, int talentType, int talentLevel) {
        int check = simpleCheck(activityId);
        if (check != 0) {
            return check;
        }

        WanYaoTalentConfig wanYaoTalentConfigByLevel = WanYaoMgr.getWanYaoTalentConfigByLevel(talentType, talentLevel);
        if (wanYaoTalentConfigByLevel == null) {
            return GameErrorCode.E_WAN_YAO_ACTIVITY_KING_TALENT_NO_EXIST;
        }

        if (wanYaoTalentConfigByLevel.getUnlock() > userData.getMonsterKingLevel()) {
            return GameErrorCode.E_WAN_YAO_ACTIVITY_KING_TALENT_NO_UNLOCK;
        }

        long oldFlower = userData.getFlowerNum();
        int cost = wanYaoTalentConfigByLevel.getCost();
        if (oldFlower < cost) {
            return GameErrorCode.E_WAN_YAO_ACTIVITY_KING_FLOWER_NO_ENOUGH;
        }
        //  先扣惊魂花 再做事务
        userData.setFlowerNum(oldFlower - cost);

        Map<Integer, WanYaoBuffData> buffDataMap = userData.getBuffDataMap();

        //返还数量
        long returnFlowerNum = 0;

        if (buffDataMap.containsKey(talentType)) {
            WanYaoBuffData buffData = buffDataMap.get(talentType);
            if (buffData.getBuffLevel() > talentLevel) {
                return GameErrorCode.E_WAN_YAO_ACTIVITY_KING_TALENT_ACTIVE_LOW;
            } else if (buffData.getBuffLevel() == talentLevel) {
                buffData.setBuffId(wanYaoTalentConfigByLevel.getId());
                buffData.setBuffTime(buffData.getBuffTime() + wanYaoTalentConfigByLevel.getTalentParaList().get(0));
            } else if (buffData.getBuffLevel() < talentLevel) {
                if (buffData.getBuffTime() > 0) {
                    returnFlowerNum = returnFlower(buffData.getType(), buffData.getBuffLevel(), buffData.getBuffTime());
                }

                buffData.setBuffId(wanYaoTalentConfigByLevel.getId());
                buffData.setBuffLevel(talentLevel);
                buffData.setBuffTime(wanYaoTalentConfigByLevel.getTalentParaList().get(0));
            }
        } else {
            WanYaoBuffData buffData = new WanYaoBuffData();
            buffData.setBuffId(wanYaoTalentConfigByLevel.getId());
            buffData.setBuffLevel(talentLevel);
            buffData.setBuffTime(wanYaoTalentConfigByLevel.getTalentParaList().get(0));
            buffData.setType(talentType);
            buffDataMap.put(talentType, buffData);
        }

        WanYaoProto.WanYaoActiveTalentRespMsg.Builder resp = WanYaoProto.WanYaoActiveTalentRespMsg.newBuilder();

        WanYaoBuffData buffData = buffDataMap.get(talentType);
        //如果是增加步数的buff 要检测是否当回合要触发
        if (buffData.getType() == eWanYaoTalentBuffType.addStep.getValue()) {
            //如果没触发过 这回合
            if (!userData.getHasAddStep()) {
                List<Integer> talentParaList = wanYaoTalentConfigByLevel.getTalentParaList();
                if (talentParaList.size() == 2) {
                    userData.setHasAddStep(true);
                    buffData.setBuffTime(buffData.getBuffTime() - 1);
                    userData.setSteps(userData.getSteps() + talentParaList.get(1));

                    WanYaoProto.WanYaoBuff.Builder buff = WanYaoProto.WanYaoBuff.newBuilder();
                    buff.setBuffType(buffData.getType());
                    buff.setBuffLevel(buffData.getBuffLevel());
                    buff.setBuffTime(1);
                    resp.setUseBuff(buff);
                }
            }
        }

        LogWanYaoActiveTalent log = new LogWanYaoActiveTalent(activityId,getUserId(),talentType,talentLevel,oldFlower,cost,returnFlowerNum,userData.getFlowerNum(),new Date());
        AutoLogMgr.add(log);

        resp.setRet(0);
        resp.setUserData(parseUserBuilder());
        if (returnFlowerNum > 0) {
            resp.setReturnFlower(returnFlowerNum);
        }

        player.sendPacket(ClientProtocol.U_WAN_YAO_ACTIVE_TALENT, resp);

        return 0;
    }

    /**
     * 返还
     */
    public long returnFlower(int buffType, int buffLevel, int remainTime) {
        if (remainTime <= 0) {
            return 0;
        }

        WanYaoTalentConfig configByLevel = WanYaoMgr.getWanYaoTalentConfigByLevel(buffType, buffLevel);
        if (configByLevel == null) {
            log.info("wan yao activity return flower talent config error activityId:{} buffType:{} buffLevel:{}", userData.getActivityId(), buffType, buffLevel);
            return 0;
        }
        List<Integer> talentParaList = configByLevel.getTalentParaList();
        if (talentParaList.isEmpty()) {
            log.info("wan yao activity return flower talent config error activityId:{} buffType:{} buffLevel:{}", userData.getActivityId(), buffType, buffLevel);
            return 0;
        }
        int onceActiveTime = talentParaList.get(0);
        long needReturnFlower = (long) configByLevel.getCost() * remainTime / onceActiveTime;

        userData.setFlowerNum(userData.getFlowerNum() + needReturnFlower);

        return needReturnFlower;
    }

    /**
     * 出行
     *
     * @param activityId
     * @return
     */

    public int goOut(int activityId) {
        int check = simpleCheck(activityId);
        if (check != 0) {
            return check;
        }

        //体力重新算一下
        calculatePower();
        int oldPower = userData.getPower();
        long oldExp = userData.getMonsterExp();
        long oldFlower = userData.getFlowerNum();
        int oldGetBoxLevel = userData.getHasGetBoxLevel();


        WanYaoMonsterKingConfig kingConfig = WanYaoMgr.getWanYaoMonsterKingConfigByLevel(userData.getMonsterKingLevel());
        if (kingConfig == null) {
            return GameErrorCode.E_WAN_YAO_ACTIVITY_CONFIG_ERROR;
        }
        int energyCost = kingConfig.getEnergyCost();
        if (userData.getPower() < energyCost) {
            return GameErrorCode.E_WAN_YAO_ACTIVITY_POWER_NO_ENOUGH;
        }

        //拷贝一份妖怪数据
        Map<Integer, WanYaoMonsterData> originalMonsterMap = userData.getMonsterDataMap();

        Map<Integer, WanYaoMonsterData> copyMap = new ConcurrentHashMap<>(originalMonsterMap);
        //检测并且添加是否有buff临时加入的怪物
        int triggerTemporaryAddMonsterBuffLevel = checkTriggerTemporaryAddMonster(copyMap);
        //检测是否可以添加
        int triggerAddMonsterPowerBuffLevel = checkTriggerAddMonsterPower();
        int atkAddition = 0;
        if (triggerAddMonsterPowerBuffLevel != 0) {
            WanYaoTalentConfig configByLevel = WanYaoMgr.getWanYaoTalentConfigByLevel(eWanYaoTalentBuffType.addAllMonsterPower.getValue(), triggerAddMonsterPowerBuffLevel);
            if (configByLevel != null) {
                atkAddition = configByLevel.getTalentParaList().get(1);
            }
        }

        //先拿最强的怪物 看看连杀
        WanYaoMonsterData strongestMonster = getStrongestMonster(copyMap);
        if (strongestMonster == null) {
            return GameErrorCode.E_WAN_YAO_ACTIVITY_NO_MONSTER;
        }


        //下面算加成buff后伤害
        long monsterPower = calculateBuffedTotalMonsterPower(copyMap, atkAddition);
        long logPower = monsterPower;


        int strongestMonsterLevel = strongestMonster.getLevel();
        WanYaoNpcConfig wanYaoNpcConfigByLevel = WanYaoMgr.getWanYaoNpcConfigByLevel(strongestMonsterLevel);
        if (wanYaoNpcConfigByLevel == null) {
            return GameErrorCode.E_WAN_YAO_ACTIVITY_CONFIG_ERROR;
        }

        WanYaoGoOutResult result = new WanYaoGoOutResult();
        result.setReward(new Property());

        int bestAtk = wanYaoNpcConfigByLevel.getAtk();
        int bestBuffAtk = bestAtk + bestAtk * atkAddition / 1000;
        //先检测一下最多击杀
        int mostKill = WanYaoMgr.checkMostKill(bestBuffAtk);
        result.setMostKillNum(mostKill);
        result.setCostBuffData(new ArrayList<>());
        WanYaoConfig wanYaoConfig = WanYaoMgr.getConfig();
        Map<Integer, WanYaoMissionConfig> wanYaoMissionConfigMap = wanYaoConfig.getWanYaoMissionConfigMap();
        if (wanYaoMissionConfigMap == null || wanYaoMissionConfigMap.isEmpty()) {
            return GameErrorCode.E_WAN_YAO_ACTIVITY_CONFIG_ERROR;
        }
        for (int outLevel = 1; outLevel <= wanYaoMissionConfigMap.size(); outLevel++) {
            WanYaoLevelData levelData;

            WanYaoMissionConfig missionConfig = wanYaoMissionConfigMap.get(outLevel);
            if (missionConfig == null) {
                return GameErrorCode.E_WAN_YAO_ACTIVITY_CONFIG_ERROR;
            }
            //小怪血量
            List<Long> enemyPowerList = missionConfig.getEnemyPowerList();
            if (enemyPowerList == null || enemyPowerList.isEmpty() || enemyPowerList.size() < 14) {
                log.error("wan yao activity config error, enemyPowerList is null or empty or size < 14, activityId = {}", activityId);
                return GameErrorCode.E_WAN_YAO_ACTIVITY_CONFIG_ERROR;
            }
            //小怪掉落惊魂花
            List<Integer> enemyFlowerList = missionConfig.getEnemyFlowerList();
            if (enemyFlowerList == null || enemyFlowerList.isEmpty() || enemyFlowerList.size() < 14) {
                log.error("wan yao activity config error, enemyFlowerList is null or empty or size < 14, activityId = {}", activityId);
                return GameErrorCode.E_WAN_YAO_ACTIVITY_CONFIG_ERROR;
            }


            int hasBeatNum = 0;
            boolean killAllSmall = true;
            boolean killBoss = false;
            long remainBlood = 0;

            //先打小怪
            for (; hasBeatNum < enemyPowerList.size(); hasBeatNum++) {
                long enemyPower = enemyPowerList.get(hasBeatNum);
                if (monsterPower < enemyPower) {
                    killAllSmall = false;
                    remainBlood = enemyPower - monsterPower;
//                    System.out.println("little lose");
//                    System.out.println("level = " + outLevel + " remainBlood = " + remainBlood + " hasBeatNum = " + hasBeatNum + " monsterPower = " + monsterPower + " enemyPower = " + enemyPower);
                    levelData = new WanYaoLevelData();
                    levelData.setLevel(outLevel);
                    levelData.setEnemyIndex(hasBeatNum);
                    levelData.setRemainBlood(remainBlood);
                    result.setLevelData(levelData);
                    break;

                } else {
                    monsterPower = monsterPower - enemyPower;
//                    System.out.println("little win");
//                    System.out.println("level = " + outLevel + " remainBlood = " + remainBlood + " hasBeatNum = " + hasBeatNum + " monsterPower = " + monsterPower + " enemyPower = " + enemyPower);
                    result.setFlowerGet(result.getFlowerGet() + enemyFlowerList.get(hasBeatNum));
                }
            }

            //如果杀了所有小怪 判断打不打得过boss
            if (killAllSmall) {
                long bossPower = missionConfig.getBossPower();
                if (bossPower <= monsterPower) {
                    killBoss = true;
                    monsterPower = monsterPower - bossPower;
//                    System.out.println("boss win");
//                    System.out.println("level = " + outLevel + " remainBlood = " + remainBlood + " hasBeatNum = " + hasBeatNum + " monsterPower = " + monsterPower + " bosspower = " + bossPower);
                }else {
                    remainBlood = bossPower - monsterPower;
                    levelData = new WanYaoLevelData();
                    levelData.setLevel(outLevel);
                    levelData.setEnemyIndex(hasBeatNum);
                    levelData.setRemainBlood(remainBlood);
                    result.setLevelData(levelData);
//                    System.out.println("boss lose");
//                    System.out.println("level = " + outLevel + " remainBlood = " + remainBlood + " hasBeatNum = " + hasBeatNum + " monsterPower = " + monsterPower + " enemyPower = " + bossPower);
                    break;
                }
            }else {
                break;
            }
            if (killBoss) {
//                System.out.println("boss win");
//                System.out.println("level = " + outLevel + " remainBlood = " + remainBlood + " hasBeatNum = " + hasBeatNum + " monsterPower = " + monsterPower + " enemyPower = " + 0);

                //boss 的惊魂花奖励
                result.setFlowerGet(result.getFlowerGet() + missionConfig.getBossBean());
                //如果领取过的最大宝箱关卡小于当前关卡，领取宝箱
                if (userData.getHasGetBoxLevel() < outLevel){
                    userData.setHasGetBoxLevel(outLevel);
                    //先加到奖励列表
                    result.addReward(PropertyHelper.parseNewStringToProperty(missionConfig.getRewards()));
                    //再加惊魂花列表
                    List<Integer> boxFlowerList = missionConfig.getBoxFlowerList();
                    for (int flowerNum : boxFlowerList) {
                        result.setFlowerGet(result.getFlowerGet() + flowerNum);
                    }
                }
                levelData = new WanYaoLevelData();
                levelData.setLevel(outLevel);
                levelData.setEnemyIndex(hasBeatNum+1);
                levelData.setRemainBlood(remainBlood);
                result.setLevelData(levelData);

            }else {
                break;
            }

        }
        WanYaoProto.WanYaoGoOutResp.Builder builder = WanYaoProto.WanYaoGoOutResp.newBuilder();
        builder.setRet(0);
        builder.setOldGetRewardLevel(oldGetBoxLevel);
        Map<Integer, Integer> triggerBuff = new HashMap<>();
        //扣除加怪buff
        if (triggerTemporaryAddMonsterBuffLevel != 0) {   //触发了一定不为空
            int reduceBuffResult = reduceBuff(eWanYaoTalentBuffType.addBattleMonster.getValue());
            if (reduceBuffResult != 0){
                return reduceBuffResult;
            }
            //发包
            WanYaoProto.WanYaoBuff.Builder buffBuilder = WanYaoProto.WanYaoBuff.newBuilder();
            buffBuilder.setBuffType(eWanYaoTalentBuffType.addBattleMonster.getValue());
            buffBuilder.setBuffTime(1);
            buffBuilder.setBuffLevel(triggerTemporaryAddMonsterBuffLevel);
            builder.addCostBuff(buffBuilder);

            userData.setUpdateOption();
            triggerBuff.put(eWanYaoTalentBuffType.addBattleMonster.getValue(), triggerTemporaryAddMonsterBuffLevel);
        }
        //扣除加妖力buff
        if (triggerAddMonsterPowerBuffLevel != 0) {
            int reduceBuffResult = reduceBuff(eWanYaoTalentBuffType.addAllMonsterPower.getValue());
            if (reduceBuffResult != 0){
                return reduceBuffResult;
            }

            //发包
            WanYaoProto.WanYaoBuff.Builder buffBuilder = WanYaoProto.WanYaoBuff.newBuilder();
            buffBuilder.setBuffType(eWanYaoTalentBuffType.addAllMonsterPower.getValue());
            buffBuilder.setBuffTime(1);
            buffBuilder.setBuffLevel(triggerAddMonsterPowerBuffLevel);
            builder.addCostBuff(buffBuilder);

            userData.setUpdateOption();
            triggerBuff.put(eWanYaoTalentBuffType.addAllMonsterPower.getValue(), triggerAddMonsterPowerBuffLevel);
        }
        //扣除加经验buff
        int checkTriggerAddExp = checkTriggerAddExp();
        if (checkTriggerAddExp != 0) {
            int reduceBuffResult = reduceBuff(eWanYaoTalentBuffType.extraExpReward.getValue());
            if (reduceBuffResult != 0){
                return reduceBuffResult;
            }

            WanYaoTalentConfig wanYaoTalentConfigByLevel = WanYaoMgr.getWanYaoTalentConfigByLevel(eWanYaoTalentBuffType.extraExpReward.getValue(), checkTriggerAddExp);
            if (wanYaoTalentConfigByLevel == null) {
                log.info("wan yao activity king talent buff no exist, activityId = {},userId = {},buffType = {}", userData.getActivityId(), userData.getUserId(), eWanYaoTalentBuffType.extraExpReward.getValue());
                return GameErrorCode.E_WAN_YAO_ACTIVITY_KING_TALENT_NO_EXIST;
            }
            int addRate = wanYaoTalentConfigByLevel.getTalentParaList().get(1);

            //发包
            WanYaoProto.WanYaoBuff.Builder buffBuilder = WanYaoProto.WanYaoBuff.newBuilder();
            buffBuilder.setBuffType(eWanYaoTalentBuffType.extraExpReward.getValue());
            buffBuilder.setBuffTime(1);
            buffBuilder.setBuffLevel(checkTriggerAddExp);
            builder.addCostBuff(buffBuilder);

            //result.setFlowerGet(result.getFlowerGet() + result.getFlowerGet() * addRate / 1000);

            userData.setUpdateOption();
            triggerBuff.put(eWanYaoTalentBuffType.extraExpReward.getValue(), checkTriggerAddExp);
        }

        //根据体力消耗获取五帝钱奖励
        int scoreItemGet = energyCost * wanYaoConfig.getScorePerEnergy();
        Property scoreReward = new Property(wanYaoConfig.getScoreItemId(), scoreItemGet);
        result.addReward(scoreReward);

        if (userData.getLevelData().getLevel() < result.getLevelData().getLevel()) {
            userData.setLevelData(result.getLevelData());
        } else if (userData.getLevelData().getLevel() == result.getLevelData().getLevel()) {
            if (userData.getLevelData().getEnemyIndex() < result.getLevelData().getEnemyIndex()) {
                userData.setLevelData(result.getLevelData());
            }
        }

        //加经验
        //热更代码
        String expReward = "0,50|20,75|40,100|60,125|80,150|100,200|140,250|180,275|200,300|220,350|240,400";
        Map<String, ActivityConfig> activityConfigMap = NormalActivityMgr.getActivityConfigMap(activityId);
        if (activityConfigMap != null && activityConfigMap.size() > 0){
            ActivityConfig activityConfig = activityConfigMap.get("WANYAO_EXPERIENCE_BASE");
            if (activityConfig != null){
                expReward = activityConfig.getValue();
            }
        }
        Map<Integer,Integer> expMap = new HashMap<>();
        List<String> strings = StringUtils.stringToStringList(expReward, "\\|");
        for (String s : strings) {
            List<Integer> list = StringUtils.stringToIntegerList(s,",");
            expMap.put(list.get(0),list.get(1));
        }
        int expPerEnergy = expMap.get(0);
        if (userData.getLevelData() != null){
            int maxLevel = userData.getLevelData().getLevel();
            for (Map.Entry<Integer, Integer> entry : expMap.entrySet()) {
                if (maxLevel >= entry.getKey() && expPerEnergy < entry.getValue()){
                    expPerEnergy = entry.getValue();
                }
            }
        }

        int expGet = energyCost * expPerEnergy;




        if (checkTriggerAddExp != 0){
            WanYaoTalentConfig wanYaoTalentConfigByLevel = WanYaoMgr.getWanYaoTalentConfigByLevel(eWanYaoTalentBuffType.extraExpReward.getValue(), checkTriggerAddExp);
            if (wanYaoTalentConfigByLevel == null){
                log.error("Wan yao activity trigger Exp buff config error activityId = {} trigger = {} ",activityId,checkTriggerAddExp);
                return GameErrorCode.E_WAN_YAO_ACTIVITY_CONFIG_ERROR;
            }
            expGet = expGet + wanYaoTalentConfigByLevel.getTalentParaList().get(1);


        }

        //扣体力 放这里防止前面弹出去
        userData.setPower(userData.getPower() - energyCost);
        //累加
        userData.setTotalCostPower(userData.getTotalCostPower() + energyCost);

        userData.setMonsterExp(userData.getMonsterExp() + expGet);
        //检测是否需要更新盘面
        boolean needCheckBlockUpdate = false;
        //检测妖王升级
        for (int i = 1; i <= wanYaoConfig.getWanYaoMonsterKingConfigMap().size(); i++) {
            int hasUpgrade = checkUpgradeMonsterKing();
            if (hasUpgrade <= 0) {
                break;
            } else {
                needCheckBlockUpdate = true;
            }
        }
        /**
         * 备份老的妖力
         */
        builder.setOldMonsterPower(userData.getMonsterPower());
        builder.setBattleMonsterPower(logPower);

        for (WanYaoMonsterData wanYaoMonsterData : copyMap.values()) {
            WanYaoProto.MonsterData.Builder monsterDataBuilder = WanYaoProto.MonsterData.newBuilder();
            monsterDataBuilder.setMonsterNum(wanYaoMonsterData.getMonsterNum());
            monsterDataBuilder.setMonsterId(wanYaoMonsterData.getLevel());
            monsterDataBuilder.setBattleAtk(WanYaoMgr.getMonsterBuffedAtk(wanYaoMonsterData.getLevel(), atkAddition));
            builder.addMonsterData(monsterDataBuilder);
        }

        if (needCheckBlockUpdate) {
            WanYaoMonsterKingConfig newKingConfig = getWanYaoMonsterKingConfigByLevel(userData.getMonsterKingLevel());
            if (newKingConfig == null) {     //没配置不管
                log.info("wan yao activity king talent buff no exist, activityId = {},userId = {},buffType = {}", userData.getActivityId(), userData.getUserId(), eWanYaoTalentBuffType.extraExpReward.getValue());
            } else {
                //如果新配置的最低等级比老的高，那么就要更新盘面
                if (newKingConfig.getXiaoYaoMin() > kingConfig.getXiaoYaoMin()) {
                    /**
                     * 备份老的妖怪
                     */
                    for (WanYaoMonsterData monsterData : originalMonsterMap.values()) {
                        WanYaoProto.MonsterData.Builder monsterDataBuilder = WanYaoProto.MonsterData.newBuilder();
                        monsterDataBuilder.setMonsterNum(monsterData.getMonsterNum());
                        monsterDataBuilder.setMonsterId(monsterData.getLevel());
                        builder.addOldMonster(monsterDataBuilder);
                    }


                    Map<Integer, WanYaoBlockData> boardData = userData.getNowBoardData();
                    WanYaoProto.WanYaoMergeParseMsg.Builder allUpgradeBuilder= WanYaoProto.WanYaoMergeParseMsg.newBuilder();
                    allUpgradeBuilder.setOldBoard(parseBoardMsg(boardData));

                    for (WanYaoBlockData blockData : boardData.values()) {
                        if (blockData.getBlockLevel() < newKingConfig.getXiaoYaoMin()) {
                            blockData.setBlockLevel(newKingConfig.getXiaoYaoMin());
                        }
                    }
                    allUpgradeBuilder.setNewBoard(parseBoardMsg(boardData));
                    builder.addMergeParse(allUpgradeBuilder.build());

                    //开始合成
                    for (int i = 0; i < 100; i++) {        //保守循环

                        WanYaoProto.WanYaoMergeParseMsg.Builder mergeBuilder = checkMerge(boardData, null);
                        if (mergeBuilder == null) {
                            break;
                        } else {
                            builder.addMergeParse(mergeBuilder.build());
                        }

                        WanYaoProto.WanYaoMergeParseMsg.Builder fallCheck = fallCheck(boardData);
                        if (fallCheck != null) {
                            builder.addMergeParse(fallCheck.build());
                        }
                    }
                }
            }

        }


        //获取惊魂花
        userData.setFlowerNum(userData.getFlowerNum() + result.getFlowerGet());
        //获取奖励
        if (result.getReward() != null && !result.getReward().isNothing()) {
            player.getModule(CurrencyModule.class).addCurrency(result.getReward(),eLogMoneyType.WanYao,eLogMoneyType.WanYaoGoOutGet);
        }



        //拿出新的config
        kingConfig = getWanYaoMonsterKingConfigByLevel(userData.getMonsterKingLevel());
        if (kingConfig == null) {
            userData.setSteps(0);
        } else {
            userData.setSteps(kingConfig.getStepCountMax());
        }
        //本回合增加步数重置
        userData.setHasAddStep(false);
        //检测是否buff加步数了
        int checkTriggerAddStepBuff = checkTriggerAddStepBuff();
        //这个是出行后触发的
        if (checkTriggerAddStepBuff != 0) {
            WanYaoProto.WanYaoBuff.Builder buffBuilder = WanYaoProto.WanYaoBuff.newBuilder();
            buffBuilder.setBuffTime(1);
            buffBuilder.setBuffType(eWanYaoTalentBuffType.addStep.getValue());
            buffBuilder.setBuffLevel(checkTriggerAddStepBuff);
            builder.addCostBuff(buffBuilder);
        }


        WanYaoProto.WanYaoLevel.Builder levelBuilder = WanYaoProto.WanYaoLevel.newBuilder();
        levelBuilder.setEnemyIndex(result.getLevelData().getEnemyIndex());
        levelBuilder.setMaxLevel(result.getLevelData().getLevel());
        levelBuilder.setRemainBlood(result.getLevelData().getRemainBlood());
        builder.setMonsterKingExp(expGet);
        builder.setThisTimeLevel(levelBuilder);
        builder.setMostKillNum(mostKill);
        builder.setFlowerNum(result.getFlowerGet());
        builder.setReward(PropertyHelper.parsePropertyToString(result.getReward()));

        builder.setUserData(parseUserBuilder());


        player.notifyListener(eGamePlayerEventType.WanYaoMissionProgress.getValue(), userData.getLevelData().getLevel());
        List<WanYaoConditionRewardData> conditionRewardList = checkAutoSendWanYaoMissionConditionReward(); //检测是否有自动发奖励的通关成就
        if (conditionRewardList != null && !conditionRewardList.isEmpty()) {
            WanYaoProto.ConditionRewardMsg.Builder conditionRewardMsgBuilder = WanYaoProto.ConditionRewardMsg.newBuilder();

            for (WanYaoConditionRewardData conditionRewardData : conditionRewardList) {
                WanYaoProto.ConditionReward.Builder conditionRewardBuilder = WanYaoProto.ConditionReward.newBuilder();
                conditionRewardBuilder.setConditionId(conditionRewardData.getConditionId());
                conditionRewardBuilder.setMissionConditionReward(conditionRewardData.getReward());
                conditionRewardMsgBuilder.addConditionReward(conditionRewardBuilder);
            }

            builder.setConditionReward(conditionRewardMsgBuilder);
        }

        player.sendPacket(ClientProtocol.U_WAN_YAO_GO_OUT, builder);
        LogWanYaoGoOut logWanYaoGoOut = new LogWanYaoGoOut(activityId,
                getUserId(),
                oldPower,
                energyCost,
                userData.getPower(),
                oldExp,
                expGet,
                userData.getMonsterExp(),
                oldFlower,
                result.getFlowerGet(),
                userData.getFlowerNum(),
                triggerBuff,
                result.getLevelData(),
                result.getMostKillNum(),
                PropertyHelper.parsePropertyToString(result.getReward()),
                new Date()
                );
        AutoLogMgr.add(logWanYaoGoOut);


        return 0;
    }

    public List<WanYaoConditionRewardData> checkAutoSendWanYaoMissionConditionReward() {
        ActivityInfo activityInfo = WanYaoMgr.getActivityInfo();
        List<WanYaoConditionRewardData> rewardList = new ArrayList<>();
        if (activityInfo == null) {
            return rewardList;
        }
        BaseActivityData baseActivityData = player.getModule(ActivityModule.class).getBaseActivityData(activityInfo.getActivityId());
        if(baseActivityData != null){

            for (BaseActivityCondition baseActivityCondition : baseActivityData.getBaseActivityConditionList()) {
                if(baseActivityCondition.getConditionType() == eGamePlayerEventType.WanYaoMissionProgress.getValue()){
                    if (!baseActivityCondition.isCompleted(player)){        //未完成
                        continue;
                    }
                    if (baseActivityCondition.isGetReward()){               //已经领奖
                        continue;
                    }
                    String reward = baseActivityCondition.getReward();
                    WanYaoConditionRewardData rewardData = new WanYaoConditionRewardData(baseActivityCondition.getConditionId(),reward);
                    rewardList.add(rewardData);
                }
            }
        }
        return rewardList;
    }

    private int reduceBuff(int type){
        WanYaoBuffData buffData = userData.getBuffDataMap().get(type);
        if (buffData == null) {
            log.info("wan yao activity king talent buff no exist, activityId = {},userId = {},buffType = {}", userData.getActivityId(), userData.getUserId(), eWanYaoTalentBuffType.addBattleMonster.getValue());
            return GameErrorCode.E_WAN_YAO_ACTIVITY_KING_TALENT_NO_EXIST;
        }
        if (buffData.getBuffTime() <= 0) {
            log.info("wan yao activity king talent buff no exist, activityId = {},userId = {},buffType = {}", userData.getActivityId(), userData.getUserId(), eWanYaoTalentBuffType.addBattleMonster.getValue());
            return GameErrorCode.E_WAN_YAO_ACTIVITY_KING_TALENT_NO_EXIST;
        }
        buffData.setBuffTime(buffData.getBuffTime() - 1);
        userData.setUpdateOption();
        return 0;
    }


    /**
     * 重新计算妖力
     */
    public void reCalculateMonsterPower() {
        Map<Integer, WanYaoMonsterData> monsterDataMap = userData.getMonsterDataMap();
        long newPower = calculateTotalMonsterPower(monsterDataMap);
        userData.setMonsterPower(newPower);
    }

    /**
     * 计算buff下的总妖力
     */
    public long calculateBuffedTotalMonsterPower(Map<Integer, WanYaoMonsterData> monsterDataMap, int buffRate) {
        if (monsterDataMap == null || monsterDataMap.isEmpty()) {
            return 0;
        }
        long totalPower = 0;
        for (WanYaoMonsterData data : monsterDataMap.values()) {
            long atk = WanYaoMgr.getMonsterBuffedAtk(data.getLevel(), buffRate);

            //  怪物战力 = 怪物攻击力 * 怪物数量
            totalPower += atk * data.getMonsterNum();
        }
        return totalPower;

    }


    /**
     * 计算总妖力
     */
    public long calculateTotalMonsterPower(Map<Integer, WanYaoMonsterData> monsterDataMap) {
        if (monsterDataMap == null || monsterDataMap.isEmpty()) {
            return 0;
        }
        long totalPower = 0;
        for (WanYaoMonsterData data : monsterDataMap.values()) {
            WanYaoNpcConfig wanYaoNpcConfigByLevel = WanYaoMgr.getWanYaoNpcConfigByLevel(data.getLevel());
            if (wanYaoNpcConfigByLevel == null) {
                log.error("WanYaoModule calculateTotalMonsterPower wanYaoNpcConfigByLevel is null level = {}", data.getLevel());
                continue;
            }
            //  怪物战力 = 怪物攻击力 * 怪物数量
            totalPower += (long) wanYaoNpcConfigByLevel.getAtk() * data.getMonsterNum();
        }
        return totalPower;


    }


    /**
     * 使用体力道具
     */
    public int usePowerItem(int activityId, int useNum) {
        int simpleCheck = simpleCheck(activityId);
        if (simpleCheck != 0) {
            return simpleCheck;
        }
        if (useNum <= 0 || useNum > 10000) {
            return GameErrorCode.E_WAN_YAO_ACTIVITY_USE_ITEM_NUM_ERROR;
        }
        calculatePower();
        WanYaoConfig config = WanYaoMgr.getConfig();
        int powerItemId = config.getPowerItemId();
        GoodsInfo goodsById = GoodsMgr.getGoodsById(powerItemId);
        if (goodsById == null) {
            return GameErrorCode.E_WAN_YAO_ACTIVITY_CONFIG_ERROR;
        }
        int recoveryPowerPerItem = goodsById.getParamList().get(0).intValue();


        Property needProperty = new Property(powerItemId, useNum);
        CurrencyModule module = player.getModule(CurrencyModule.class);
        if (!module.currencyIsEnough(needProperty)) {
            return GameErrorCode.E_WAN_YAO_ACTIVITY_ITEM_NO_ENOUGH;
        }
        if (!module.removeCurrency(needProperty, eLogMoneyType.WanYao, eLogMoneyType.WanYaoUsePowerItem)) {
            return GameErrorCode.E_WAN_YAO_ACTIVITY_ITEM_NO_ENOUGH;
        }


        userData.setPower(userData.getPower() + useNum * recoveryPowerPerItem);
        WanYaoProto.WanYaoUsePowerItemRespMsg.Builder resp = WanYaoProto.WanYaoUsePowerItemRespMsg.newBuilder();
        resp.setRet(0);
        resp.setNowPower(userData.getPower());
        resp.setLastRecoveryTime(userData.getLastPowerRecTime());
        player.sendPacket(ClientProtocol.U_WAN_YAO_USE_POWER_ITEM, resp);

        return 0;
    }

    /**
     * 更新体力
     */

    private void calculatePower() {
        if (userData == null) {
            return;
        }

        WanYaoConfig config = WanYaoMgr.getConfig();
        if (config == null) {
            return;
        }

        CalcPowerResult calcPowerResult = PowerHelper.calcPower(userData.getLastPowerRecTime() / 1000, config.getPowerCdTime(), 1, config.getPowerMax(), userData.getPower());
        userData.setPower(calcPowerResult.getCurPower());
        userData.setLastPowerRecTime(calcPowerResult.getLastRecoverTime() * 1000);
    }


    /**
     * 获取最强的怪物
     */
    public WanYaoMonsterData getStrongestMonster(Map<Integer, WanYaoMonsterData> monsterDataMap) {
        WanYaoMonsterData monsterData = null;
        for (WanYaoMonsterData data : monsterDataMap.values()) {
            if (monsterData == null) {
                monsterData = data;
            } else {
                if (data.getLevel() > monsterData.getLevel()) {
                    monsterData = data;
                }
            }
        }
        return monsterData;
    }


    /**
     * 简单检查
     *
     * @param activityId
     * @return
     */
    public int simpleCheck(int activityId) {
        ActivityInfo activityInfo = WanYaoMgr.getActivityInfo();
        if (activityInfo == null) {
            return GameErrorCode.E_WAN_YAO_ACTIVITY_NO_OPEN;
        }
        if (activityInfo.getActivityId() != activityId) {
            return GameErrorCode.E_WAN_YAO_ACTIVITY_ID_ERROR;
        }
        if (!ActivityMgr.activityInTime(activityInfo)) {
            return GameErrorCode.E_WAN_YAO_ACTIVITY_NO_IN_TIME;
        }

        if (!SystemOpenMgr.systemOpen(player, eSystemId.WanYao.getValue())) {
            return GameErrorCode.E_WAN_YAO_ACTIVITY_NO_UNLOCK;
        }
        if (WanYaoMgr.getConfig() == null) {
            return GameErrorCode.E_WAN_YAO_ACTIVITY_CONFIG_ERROR;
        }
        if (userData == null) {
            initUserData();
        }
        if (userData == null) {
            return GameErrorCode.E_WAN_YAO_ACTIVITY_NO_OPEN;
        }

        return 0;
    }

    /**
     * 主动获取玩家数据消息
     */
    public int getUserDataMsg(int activityId) {
        int check = simpleCheck(activityId);
        if (check != 0) {
            return check;
        }

        WanYaoProto.WanYaoGetUserDataResp.Builder userMsg = WanYaoProto.WanYaoGetUserDataResp.newBuilder();
        userMsg.setRet(0);
        userMsg.setUserData(parseUserBuilder());
        player.sendPacket(ClientProtocol.U_WAN_YAO_GET_USER_DATA, userMsg);
        return 0;
    }

    /**
     * 操作方块 1升级 2上阵
     *
     * @param operateType
     * @param blockId
     * @param x
     * @param y
     * @return
     */
    public int operateBlock(int activityId, int operateType, int blockId, int x, int y) {
        //七七八八判断
        int check = simpleCheck(activityId);
        if (check != 0) {
            return check;
        }
        if (userData.getSteps() <= 0){
            return GameErrorCode.E_WAN_YAO_ACTIVITY_NO_STEP;
        }

        WanYaoBlockData wanYaoBlockData = userData.getNowBoardData().get(blockId);
        if (wanYaoBlockData == null) {
            return GameErrorCode.E_WAN_YAO_ACTIVITY_BLOCK_NO_EXIST;
        }
        if (wanYaoBlockData.getX() != x || wanYaoBlockData.getY() != y) {
            return GameErrorCode.E_WAN_YAO_ACTIVITY_BLOCK_POSITION_ERROR;
        }
        if (wanYaoBlockData.getBlockLevel() >= MAX_LEVEL && operateType == 1) {
            return GameErrorCode.E_WAN_YAO_ACTIVITY_BLOCK_LEVEL_MAX;
        }
        //如果当前操作的是最高级 被锁住了
        int maxLevel = getMaxLevel();
        if (maxLevel < 0) {
            return GameErrorCode.E_WAN_YAO_ACTIVITY_BLOCK_POSITION_ERROR;
        }

        if (maxLevel <= wanYaoBlockData.getBlockLevel() && operateType == 1) {
            return GameErrorCode.E_WAN_YAO_ACTIVITY_BLOCK_LEVEL_MAX;
        }

        userData.setSteps(userData.getSteps() - 1);
        //引导
        if (userData.getGuideStep() == 0){
            guide(activityId,1);
            return 0;
        }else if (userData.getGuideStep() == 1){
            guide(activityId,2);
            return 0;
        }

        //复制一份操作方块 log用
        WanYaoBlockData copyBlockData = wanYaoBlockData.copy();
        //复制一份老的妖怪map log用
        Map<Integer,Integer> oldMonsterMap = new HashMap<>();
        for (WanYaoMonsterData monsterData : userData.getMonsterDataMap().values()){
            oldMonsterMap.put(monsterData.getLevel(),monsterData.getMonsterNum());
        }
        //复制老妖力 log用
        reCalculateMonsterPower();
        long oldPower = userData.getMonsterPower();

        //-------------------------开始操作----------
        List<WanYaoProto.WanYaoMergeParseMsg> operateResult = operate(operateType, blockId);
        if (operateResult == null) {
            return GameErrorCode.E_WAN_YAO_ACTIVITY_BLOCK_OPERATE_ERROR;
        }
        reCalculateMonsterPower();
        player.notifyListener(eGamePlayerEventType.WanYaoUserPowerRank.getValue(), userData.getMonsterPower());
        //------------------------操作结束----------------

        //新的妖怪map log用
        Map<Integer,Integer> newMonsterMap = new HashMap<>();
        for (WanYaoMonsterData monsterData : userData.getMonsterDataMap().values()){
            newMonsterMap.put(monsterData.getLevel(),monsterData.getMonsterNum());
        }
        //新生成的方块List log用
        List<WanYaoBlockData> newBlockList = new ArrayList<>();
        //上阵的怪物log用
        Map<Integer,Integer> upMonsterMap = new HashMap<>();
        //触发buff log用
        Map<Integer,Integer> buffTrigger = new HashMap<>();


        for (WanYaoProto.WanYaoMergeParseMsg msg:operateResult){
            for (WanYaoProto.WanYaoSingleMergeMsg singleMergeMsg:msg.getSingleMergeList()){
                if (singleMergeMsg.hasNewBlock()){
                    WanYaoProto.WanYaoBlockMsg newBlock = singleMergeMsg.getNewBlock();
                    WanYaoBlockData blockData = new WanYaoBlockData();
                    blockData.setBlockId(newBlock.getId());
                    blockData.setBlockLevel(newBlock.getLevel());
                    blockData.setX(newBlock.getX());
                    blockData.setY(newBlock.getY());
                    newBlockList.add(blockData);
                }
                List<WanYaoProto.MonsterData> newMonsterList = singleMergeMsg.getNewMonsterList();
                if (!newMonsterList.isEmpty()){
                    for (WanYaoProto.MonsterData monsterData:newMonsterList){
                        if (upMonsterMap.containsKey(monsterData.getMonsterId())){
                            upMonsterMap.put(monsterData.getMonsterId(),upMonsterMap.get(monsterData.getMonsterId())+monsterData.getMonsterNum());
                        }else {
                            upMonsterMap.put(monsterData.getMonsterId(),monsterData.getMonsterNum());
                        }
                    }
                }
                List<WanYaoProto.WanYaoBuff> triggerBuffTimeList = singleMergeMsg.getTriggerBuffTimeList();
                if (!triggerBuffTimeList.isEmpty()){
                    for (WanYaoProto.WanYaoBuff buff:triggerBuffTimeList){
                        buffTrigger.put(buff.getBuffType(),buff.getBuffLevel());
                    }
                }
            }
        }

        LogWanYaoOperateBlock log = new LogWanYaoOperateBlock(activityId,
                getUserId(),
                operateType,
                copyBlockData,
                newBlockList,
                oldMonsterMap,
                upMonsterMap,
                newMonsterMap,
                buffTrigger,
                userData.getMonsterKingLevel(),
                oldPower,
                userData.getMonsterPower(),
                userData.getSteps(),
                new Date()
                );
        AutoLogMgr.add(log);
        WanYaoProto.OperateWanYaoBoardResp.Builder resp = WanYaoProto.OperateWanYaoBoardResp.newBuilder();
        resp.setRet(0);
        resp.setOperateType(operateType);
        resp.setId(blockId);
        resp.addAllMergeParse(operateResult);
        resp.setUserData(parseUserBuilder());
        player.sendPacket(ClientProtocol.U_WAN_YAO_OPERATE_BOARD, resp);

        return 0;
    }

    public int getMaxLevel() {
        Optional<WanYaoBlockData> max = userData.getNowBoardData().values().stream().max(Comparator.comparingInt(WanYaoBlockData::getBlockLevel));
        return max.map(WanYaoBlockData::getBlockLevel).orElse(0);
    }


    public void syncConfig() {
        if (WanYaoMgr.getActivityInfo() == null) {
            return;
        }

        WanYaoProto.WanYaoConfigSync.Builder configMsg = WanYaoMgr.getConfigMsg(player.getLanguage());
        if (configMsg == null) {
            return;
        }
        player.sendPacket(ClientProtocol.U_WAN_YAO_SYNC_CONFIG, configMsg);
    }

    public void syncUserData() {
        if (WanYaoMgr.getActivityInfo() == null || WanYaoMgr.getConfig() == null) {
            return;
        }
        initUserData();
        if (userData == null) {
            return;
        }
        if (userData.getNowBoardData() == null){
            userData.setNowBoardData(WanYaoMgr.getInitBoardData(0));
            userData.setSteps(WanYaoMgr.getMaxStepByLevel(1));
            userData.setPower(WanYaoMgr.getOriginalPower());
        }
        WanYaoProto.syncWanYaoUserData.Builder userMsg = WanYaoProto.syncWanYaoUserData.newBuilder();
        userMsg.setUserData(parseUserBuilder());
        player.sendPacket(ClientProtocol.U_WAN_YAO_SYNC_USER_DATA, userMsg);
    }

    public void initUserData() {
        if (!SystemOpenMgr.systemOpen(player,eSystemId.WanYao.getValue())){
            return;
        }

        ActivityInfo activityInfo = WanYaoMgr.getActivityInfo();
        if (activityInfo == null || WanYaoMgr.getConfig() == null) {
            return;
        }
        if (userData != null && userData.getActivityId() == activityInfo.getActivityId()) {
            return;
        }
        WanYaoUserData tmpUserData = new WanYaoUserData();
        tmpUserData.setActivityId(activityInfo.getActivityId());
        tmpUserData.setUserId(getUserId());
        tmpUserData.setMonsterPower(0);
        tmpUserData.setMonsterKingLevel(1);
        tmpUserData.setMonsterExp(0);
        tmpUserData.setBuffDataMap(new ConcurrentHashMap<>());
        tmpUserData.setPower(WanYaoMgr.getOriginalPower());
        tmpUserData.setLastPowerRecTime(System.currentTimeMillis());
        tmpUserData.setSteps(WanYaoMgr.getMaxStepByLevel(1));
        tmpUserData.setFlowerNum(0);
        WanYaoLevelData levelData = WanYaoMgr.getInitWanYaoLevelData();
        tmpUserData.setLevelData(levelData);
        tmpUserData.setNowBoardData(WanYaoMgr.getInitBoardData(0));
        tmpUserData.setMonsterDataMap(new ConcurrentHashMap<>());
        tmpUserData.setHasAddStep(false);
        tmpUserData.setTotalCostPower(0);
        tmpUserData.setHasGetBoxLevel(0);
        tmpUserData.setGuideStep(0);
        tmpUserData.setInsertOption();
        userData = tmpUserData;
    }


    public WanYaoProto.WanYaoUserData.Builder parseUserBuilder() {
        WanYaoProto.WanYaoUserData.Builder builder = WanYaoProto.WanYaoUserData.newBuilder();
        builder.setMonsterPower(userData.getMonsterPower());
        builder.setMonsterKingLevel(userData.getMonsterKingLevel());
        builder.setMonsterKingExp(userData.getMonsterExp());
        WanYaoProto.WanYaoBuff.Builder buffBuilder = WanYaoProto.WanYaoBuff.newBuilder();
        for (WanYaoBuffData buffData : userData.getBuffDataMap().values()) {
            buffBuilder.setBuffType(buffData.getType());
            buffBuilder.setBuffLevel(buffData.getBuffLevel());
            buffBuilder.setBuffTime(buffData.getBuffTime());
            builder.addBuffs(buffBuilder);
        }
        builder.setPower(userData.getPower());
        builder.setLastRecoveryPowerTime(userData.getLastPowerRecTime());
        builder.setSteps(userData.getSteps());
        builder.setFlowerNum(userData.getFlowerNum());

        WanYaoProto.WanYaoLevel.Builder levelBuilder = WanYaoProto.WanYaoLevel.newBuilder();
        levelBuilder.setMaxLevel(userData.getLevelData().getLevel());

        levelBuilder.setEnemyIndex(userData.getLevelData().getEnemyIndex());
        levelBuilder.setRemainBlood(userData.getLevelData().getRemainBlood());
        builder.setMaxLevel(levelBuilder);


        WanYaoProto.WanYaoBoardMsg.Builder boardBuilder = parseBoardMsg(userData.getNowBoardData());

        builder.setBoards(boardBuilder);

        for (WanYaoMonsterData monsterData : userData.getMonsterDataMap().values()) {
            WanYaoProto.MonsterData.Builder monsterBuilder = WanYaoProto.MonsterData.newBuilder();
            monsterBuilder.setMonsterId(monsterData.getLevel());
            monsterBuilder.setMonsterNum(monsterData.getMonsterNum());
            builder.addMonsterData(monsterBuilder);
        }
        builder.setHasGetBoxLevel(userData.getHasGetBoxLevel());
        builder.setGuideStep(userData.getGuideStep());

        return builder;
    }

    /**
     * 操作
     * mainOp
     * @param operateType
     * @param id
     * @return
     */

    public List<WanYaoProto.WanYaoMergeParseMsg> operate(int operateType, int id) {
        //所有操作记录
        List<WanYaoProto.WanYaoMergeParseMsg> mergeMsgList = new ArrayList<>();
        //玩家的第一次操作记录
        WanYaoProto.WanYaoMergeParseMsg.Builder userOperateMsg = WanYaoProto.WanYaoMergeParseMsg.newBuilder();
        //保留主动操作的旧盘面
        Map<Integer, WanYaoBlockData> boardData = userData.getNowBoardData();
        userOperateMsg.setOldBoard(parseBoardMsg(boardData));
        printBoard(boardData);
        //获取主动操作的方块
        WanYaoBlockData wanYaoBlockData = boardData.get(id);
        WanYaoBlockData operateForceBlock = null;
        if (operateType == 1) {
            //先正常升级一个等级
            wanYaoBlockData.setBlockLevel(wanYaoBlockData.getBlockLevel() + 1);
            WanYaoProto.WanYaoSingleMergeMsg.Builder singleMergeMsg = WanYaoProto.WanYaoSingleMergeMsg.newBuilder();    //单次合成消息
            singleMergeMsg.setNewBlock(parseBlockMsg(wanYaoBlockData));
            if (wanYaoBlockData.getBlockLevel() < MAX_LEVEL){   //只有没满级的需要检测 //满级的不浪费buff
                int triggerId = checkTriggerOperateBuff();                                                                  //检测是否触发了buff
                if (triggerId != 0) {    //如果触发了
                    WanYaoTalentConfig wanYaoTalentConfigById = WanYaoMgr.getWanYaoTalentConfigById(triggerId);
                    if (wanYaoTalentConfigById != null) {
                        int extraLevel = wanYaoTalentConfigById.getTalentParaList().get(2);
                        //加额外等级
                        wanYaoBlockData.setBlockLevel(wanYaoBlockData.getBlockLevel() + extraLevel);
                        if (wanYaoBlockData.getBlockLevel() > MAX_LEVEL){
                            wanYaoBlockData.setBlockLevel(MAX_LEVEL);
                        }
                        singleMergeMsg.setNewBlock(parseBlockMsg(wanYaoBlockData));
                        WanYaoProto.WanYaoBuff.Builder buffBuilder = WanYaoProto.WanYaoBuff.newBuilder();
                        //加入触发buff到单次合成记录中
                        buffBuilder.setBuffType(eWanYaoTalentBuffType.extraMonsterLevel.getValue());
                        buffBuilder.setBuffLevel(wanYaoTalentConfigById.getLevel());
                        buffBuilder.setBuffTime(1);
                        singleMergeMsg.addTriggerBuffTime(buffBuilder);
                    } else {
                        log.error("wanYaoTalentConfigById is null,activityId = {},triggerId = {}", userData.getActivityId(), triggerId);
                    }

                }
            }


            //检测新生成的方块是否可以合成 上阵
            int maxBlockLevelByKingLevel = WanYaoMgr.getMaxBlockLevelByKingLevel(userData.getMonsterKingLevel());
            if (wanYaoBlockData.getBlockLevel() >= maxBlockLevelByKingLevel) {     //如果大于最高等级 自动上阵

                singleMergeMsg.setNewBlock(parseBlockMsg(wanYaoBlockData));
                //加怪物
                int blockLevel = wanYaoBlockData.getBlockLevel();
                addMonster(blockLevel, 1);
                //清空等级
                wanYaoBlockData.setBlockLevel(0);

                WanYaoProto.MonsterData.Builder monsterData = WanYaoProto.MonsterData.newBuilder();
                monsterData.setMonsterId(blockLevel);
                monsterData.setMonsterNum(1);

                singleMergeMsg.addNewMonster(monsterData);
                reCalculateMonsterPower();
                singleMergeMsg.setNewMonsterPower(userData.getMonsterPower());

            }
            singleMergeMsg.setNewMonsterPower(userData.getMonsterPower());
            userOperateMsg.addSingleMerge(singleMergeMsg);
            operateForceBlock = wanYaoBlockData;
        } else {
            int oldLevel = wanYaoBlockData.getBlockLevel();
            wanYaoBlockData.setBlockLevel(0);

            WanYaoProto.WanYaoSingleMergeMsg.Builder singleMergeMsg = WanYaoProto.WanYaoSingleMergeMsg.newBuilder();
            singleMergeMsg.setNewBlock(parseBlockMsg(wanYaoBlockData));

            WanYaoProto.MonsterData.Builder monsterData = WanYaoProto.MonsterData.newBuilder();
            monsterData.setMonsterId(oldLevel);
            monsterData.setMonsterNum(1);
            singleMergeMsg.addNewMonster(monsterData);
            addMonster(oldLevel, 1);

            reCalculateMonsterPower();
            singleMergeMsg.setNewMonsterPower(userData.getMonsterPower());


            userOperateMsg.addSingleMerge(singleMergeMsg);

        }
        //获取主动操作后的盘面
        userOperateMsg.setNewBoard(parseBoardMsg(boardData));
        printBoard(boardData);
        //添加到操作记录
        mergeMsgList.add(userOperateMsg.build());
        //先查看第一次是否造成掉落 只有手动上阵 触发buff两次升级 导致上阵有掉落
        WanYaoProto.WanYaoMergeParseMsg.Builder firstFallBuilder = fallCheck(boardData);
        if (firstFallBuilder != null) {
            //System.out.println("diao luo");
            printBoard(boardData);
            mergeMsgList.add(firstFallBuilder.build());
        }

        //开始合成
        for (int i = 0; i < 1000; i++) {        //保守循环个1000次吧

            WanYaoProto.WanYaoMergeParseMsg.Builder builder = checkMerge(boardData, operateForceBlock);
            if (builder == null) {
                break;
            } else {
                operateForceBlock = null;
                mergeMsgList.add(builder.build());
            }

            WanYaoProto.WanYaoMergeParseMsg.Builder fallCheck = fallCheck(boardData);
            if (fallCheck != null) {
                mergeMsgList.add(fallCheck.build());
            }
        }

        return mergeMsgList;


    }


    /**
     * 检测相同x并且y相邻的方块或者相同y并且x相邻的方块是否可以连成三个以上
     */
    public WanYaoProto.WanYaoMergeParseMsg.Builder checkMerge(Map<Integer, WanYaoBlockData> boardData, WanYaoBlockData userOperateBlockData) {

        int maxBlockLevelByKingLevel = WanYaoMgr.getMaxBlockLevelByKingLevel(userData.getMonsterKingLevel());

        printBoard(boardData);
        WanYaoProto.WanYaoMergeParseMsg.Builder mergeMsg = WanYaoProto.WanYaoMergeParseMsg.newBuilder();
        mergeMsg.setOldBoard(parseBoardMsg(boardData));

        List<List<WanYaoBlockData>> canMergeBlockList = new ArrayList<>();

        //拿出同等级的
        Map<Integer, List<WanYaoBlockData>> sameLevelBlockMap = new ConcurrentHashMap<>();
        for (WanYaoBlockData wanYaoBlockData : boardData.values()) {
            sameLevelBlockMap.putIfAbsent(wanYaoBlockData.getBlockLevel(), new ArrayList<>());
            sameLevelBlockMap.get(wanYaoBlockData.getBlockLevel()).add(wanYaoBlockData);
        }
        List<WanYaoBlockData> hasUsedBlock = new ArrayList<>();

        //获取同等级的方块列表
        for (List<WanYaoBlockData> sameLevelBlockDataList : sameLevelBlockMap.values()) {
            //如果同等级的方块数量小于3个 则不用合成
            if (sameLevelBlockDataList.size() < 3) {
                //不用合成的
                continue;
            }

            //开始遍历
            for (WanYaoBlockData wanYaoBlockData : sameLevelBlockDataList) {
                //栈初始化 每次从一个新方块开始遍历都需要初始化栈
                Stack<WanYaoBlockData> stack = new Stack<>();
                //如果已在合成列表里面 则不用再次合成
                if (hasUsedBlock.contains(wanYaoBlockData)) {
                    continue;
                }
                //相近方块
                List<WanYaoBlockData> hasNearList = new ArrayList<>();
                //第一个遍历的添加到相近方块列表
                hasNearList.add(wanYaoBlockData);
                //推入栈内
                stack.push(wanYaoBlockData);
                //先取第一个
                WanYaoBlockData tmpBlock = wanYaoBlockData;
                while (!stack.isEmpty()) {
                    //获取相邻的方块
                    WanYaoBlockData newNearBlock = getNewNearBlock(boardData, tmpBlock, hasNearList);
                    //如果相邻的方块不为空
                    if (newNearBlock != null) {
                        stack.push(newNearBlock);       //入栈
                        hasNearList.add(newNearBlock);  //添加到相近方块列表
                        tmpBlock = stack.peek();        //取出栈顶元素开始遍历
                    } else {                             //如果相邻的方块为空
                        stack.pop();                    //出栈
                        if (stack.isEmpty()) {           //如果栈为空
                            break;                      //退出循环
                        }
                        tmpBlock = stack.peek();
                    }
                }
                //如果相近方块数量大于等于3个
                if (hasNearList.size() >= 3) {
                    //可以合成列表添加
                    canMergeBlockList.add(hasNearList);
                    //已经使用过的方块添加
                    hasUsedBlock.addAll(hasNearList);
                }
            }
        }

        if (canMergeBlockList.isEmpty()) {
            return null;
        }


        //如果有合成
        while (!canMergeBlockList.isEmpty()) {
            //获取第一个可以合成的列表
            List<WanYaoBlockData> canMergeBlock = getFistMerge(canMergeBlockList);
            if (canMergeBlock.size() < 3) {
                canMergeBlockList.remove(canMergeBlock);
                continue;
            }
            int needNewMonster = canMergeBlock.size() - 2;
            WanYaoProto.WanYaoSingleMergeMsg.Builder singleMergeMsg = WanYaoProto.WanYaoSingleMergeMsg.newBuilder();
            singleMergeMsg.setNewMonsterPower(userData.getMonsterPower());

            //获取当前合成列表 y最小 x最小的方块
            WanYaoBlockData mergeTo = getMinBlock(canMergeBlock);
            if (userOperateBlockData != null && canMergeBlock.contains(userOperateBlockData)) {
                mergeTo = userOperateBlockData;
                userOperateBlockData = null;
            }

            //旧等级
            int oldLevel = mergeTo.getBlockLevel();
            //需要升的等级是合成列表的数量-2
            int needAddLevel = canMergeBlock.size() - 2;
            //如果需要升的等级大于7 则最多升7级
            if (needAddLevel > 7){
                needAddLevel = 7;
            }
            //如果需要升的等级大于最大等级 则最多升到最大等级
            if (oldLevel + needAddLevel > maxBlockLevelByKingLevel) {
                mergeTo.setBlockLevel(maxBlockLevelByKingLevel);
            }else {
                mergeTo.setBlockLevel(oldLevel + needAddLevel);
            }

            singleMergeMsg.setNewBlock(parseBlockMsg(mergeTo));
            for (int i = 0; i < canMergeBlock.size(); i++) {
                WanYaoBlockData mergeFrom = canMergeBlock.get(i);
                if (mergeFrom.equals(mergeTo)) {
                    continue;
                }
                mergeFrom.setBlockLevel(0);
                singleMergeMsg.addBlocks(parseBlockMsg(mergeFrom));
            }

            //先清掉已经合成的
            canMergeBlockList.remove(canMergeBlock);

            if (needNewMonster > 0) {
                addMonster(oldLevel, needNewMonster);
                WanYaoProto.MonsterData.Builder monsterData = WanYaoProto.MonsterData.newBuilder();
                monsterData.setMonsterId(oldLevel);
                monsterData.setMonsterNum(needNewMonster);
                singleMergeMsg.addNewMonster(monsterData);
                reCalculateMonsterPower();
                singleMergeMsg.setNewMonsterPower(userData.getMonsterPower());
            }

            //检测新生成的方块是否可以合成 上阵
            if (mergeTo.getBlockLevel() >= maxBlockLevelByKingLevel) {     //如果大于最高等级 自动上阵
                //加怪物
                int blockLevel = mergeTo.getBlockLevel();
                addMonster(blockLevel, 1);
                //清空等级
                mergeTo.setBlockLevel(0);

                WanYaoProto.MonsterData.Builder monsterData = WanYaoProto.MonsterData.newBuilder();
                monsterData.setMonsterId(blockLevel);
                monsterData.setMonsterNum(1);
                singleMergeMsg.addNewMonster(monsterData);
                reCalculateMonsterPower();
                singleMergeMsg.setNewMonsterPower(userData.getMonsterPower());

            } else {
                checkNewBlockCanMerge(canMergeBlockList, mergeTo,hasUsedBlock);
            }
            //稳定盘面过程添加单次合成消息
            mergeMsg.addSingleMerge(singleMergeMsg);

            printBoard(boardData);
        }

        mergeMsg.setNewBoard(parseBoardMsg(boardData));

        return mergeMsg;


    }

    /**
     * 给玩家身上加怪物
     */
    public void addMonster(int level, int num) {
        if (level <= 0 || num <= 0) {
            return;
        }
        Map<Integer, WanYaoMonsterData> monsterDataMap = userData.getMonsterDataMap();
        if (monsterDataMap == null) {
            monsterDataMap = new ConcurrentHashMap<>();
            userData.setMonsterDataMap(monsterDataMap);
        }
        if (monsterDataMap.get(level) == null) {
            WanYaoMonsterData wanYaoMonsterData = new WanYaoMonsterData();
            wanYaoMonsterData.setLevel(level);
            wanYaoMonsterData.setMonsterNum(num);
            monsterDataMap.put(level, wanYaoMonsterData);
        } else {
            WanYaoMonsterData wanYaoMonsterData = monsterDataMap.get(level);
            wanYaoMonsterData.setMonsterNum(wanYaoMonsterData.getMonsterNum() + num);
        }
        userData.setUpdateOption();
        player.notifyListener(eGamePlayerEventType.WanYaoAddMonsterCondition.getValue(),new WanYaoAddMonsterArgs(level,num));

    }

    /**
     * 升级妖王！
     */
    public int checkUpgradeMonsterKing() {

        WanYaoConfig config = WanYaoMgr.getConfig();
        if (config == null) {
            return 0;
        }
        int oldKingLevel = userData.getMonsterKingLevel();
        int newKingLevel = oldKingLevel + 1;

        WanYaoMonsterKingConfig oldLevelConfig = getWanYaoMonsterKingConfigByLevel(oldKingLevel);
        int needExp = oldLevelConfig.getCost();
        if (needExp < 0) {
            return 0;
        }
        WanYaoMonsterKingConfig newLevelConfig = getWanYaoMonsterKingConfigByLevel(newKingLevel);
        if (newLevelConfig == null) {
            return 0;
        }
        if (userData.getMonsterExp() < needExp) {
            return 0;
        }
        //userData.setMonsterExp(userData.getMonsterExp() - needExp); 不扣 做累加
        userData.setMonsterKingLevel(newKingLevel);
        userData.setUpdateOption();

//        WanYaoProto.WanYaoUpgradeMonsterKingRespMsg.Builder respMsg = WanYaoProto.WanYaoUpgradeMonsterKingRespMsg.newBuilder();
//        respMsg.setRet(0);
//        respMsg.setUserData(parseUserBuilder());
//        player.sendPacket(ClientProtocol.U_WAN_YAO_UPGRADE_MONSTER_KING, respMsg);

        return 1;
    }


    /**
     * 获取最小方块
     *
     * @param canMergeBlockList
     * @return
     */

    public WanYaoBlockData getMinBlock(List<WanYaoBlockData> canMergeBlockList) {
        WanYaoBlockData minBlock = null;
        for (WanYaoBlockData wanYaoBlockData : canMergeBlockList) {
            if (minBlock == null) {
                minBlock = wanYaoBlockData;
            } else {
                //对比y
                if (minBlock.getY() > wanYaoBlockData.getY()) {
                    minBlock = wanYaoBlockData;
                }
                //对比x
                else if (minBlock.getY() == wanYaoBlockData.getY()) {
                    if (minBlock.getX() > wanYaoBlockData.getX()) {
                        minBlock = wanYaoBlockData;
                    }
                } else { //爬
                    continue;
                }
            }
        }
        return minBlock;
    }

    /**
     * 检测新生成的方块是否可以放入合成列表
     */
    public void checkNewBlockCanMerge(List<List<WanYaoBlockData>> canMergeBlockList, WanYaoBlockData newBlock,List<WanYaoBlockData> hasUsedBlock) {
        if (newBlock == null || canMergeBlockList == null || canMergeBlockList.isEmpty()) {
            return;
        }
        for (int i = 0; i < canMergeBlockList.size(); i++) {
            Map<Integer, WanYaoBlockData> canMergeBlockMap = new ConcurrentHashMap<>();
            List<WanYaoBlockData> canMergeBlock = canMergeBlockList.get(i);
            //模拟盘面
            for (WanYaoBlockData tmpData : canMergeBlock) {
                canMergeBlockMap.put(tmpData.getBlockId(), tmpData);
            }
            //获取新方块的相邻方块
            WanYaoBlockData nearBlock = getNewNearBlock(canMergeBlockMap, newBlock, new ArrayList<>());
            if (nearBlock != null) {
                //先把新方块加入合成
                canMergeBlock.add(newBlock);

                //栈初始化 每次从一个新方块开始遍历都需要初始化栈
                Stack<WanYaoBlockData> stack = new Stack<>();
                //推入栈内
                stack.push(newBlock);
                //先取第一个
                WanYaoBlockData tmpBlock = newBlock;
                while (!stack.isEmpty()) {
                    //获取相邻的方块
                    WanYaoBlockData newNearBlock = getNewNearBlock(userData.getNowBoardData(), tmpBlock, hasUsedBlock);
                    //如果相邻的方块不为空
                    if (newNearBlock != null) {
                        stack.push(newNearBlock);       //入栈
                        hasUsedBlock.add(newNearBlock);  //添加到相近方块列表
                        canMergeBlock.add(newNearBlock); //添加到合成列表
                        tmpBlock = stack.peek();        //取出栈顶元素开始遍历
                    } else {                             //如果相邻的方块为空
                        stack.pop();                    //出栈
                        if (stack.isEmpty()) {           //如果栈为空
                            break;                      //退出循环
                        }
                        tmpBlock = stack.peek();
                    }
                }

                return;
            }
        }

    }


    /**
     * 排序合成顺序 查看谁先合成
     *
     * @param canMergeBlockList
     */

    public List<WanYaoBlockData> getFistMerge(List<List<WanYaoBlockData>> canMergeBlockList) {
        if (canMergeBlockList.size() == 1) {
            return canMergeBlockList.get(0);
        }
        List<WanYaoBlockData> minBlockList = null;
        WanYaoBlockData minBlock = null;

        for (int i = 0; i < canMergeBlockList.size(); i++) {
            if (minBlockList == null) {
                minBlockList = canMergeBlockList.get(i);
                minBlock = getMinBlock(minBlockList);
            } else {
                List<WanYaoBlockData> tmpBlockList = canMergeBlockList.get(i);
                WanYaoBlockData tmpBlock = getMinBlock(tmpBlockList);
                if (minBlock.getY() > tmpBlock.getY()) {
                    minBlockList = tmpBlockList;
                    minBlock = tmpBlock;
                } else if (minBlock.getY() == tmpBlock.getY()) {
                    if (minBlock.getX() > tmpBlock.getX()) {
                        minBlockList = tmpBlockList;
                        minBlock = tmpBlock;
                    }
                }
            }
        }
        return minBlockList;
    }


    /**
     * 获取相邻同等级的方块
     */
    public WanYaoBlockData getNewNearBlock(Map<Integer, WanYaoBlockData> boardData, WanYaoBlockData wanYaoBlockData, List<WanYaoBlockData> hasList) {

        if (wanYaoBlockData.getX() > 0) {
            WanYaoBlockData leftBlock = getBlockByXY(boardData, wanYaoBlockData.getX() - 1, wanYaoBlockData.getY());
            if (leftBlock != null && leftBlock.getBlockLevel() == wanYaoBlockData.getBlockLevel() && !hasList.contains(leftBlock)) {
                return leftBlock;
            }
        }
        if (wanYaoBlockData.getX() < 4) {
            WanYaoBlockData rightBlock = getBlockByXY(boardData, wanYaoBlockData.getX() + 1, wanYaoBlockData.getY());
            if (rightBlock != null && rightBlock.getBlockLevel() == wanYaoBlockData.getBlockLevel() && !hasList.contains(rightBlock)) {
                return rightBlock;
            }
        }
        if (wanYaoBlockData.getY() > 0) {
            WanYaoBlockData downBlock = getBlockByXY(boardData, wanYaoBlockData.getX(), wanYaoBlockData.getY() - 1);
            if (downBlock != null && downBlock.getBlockLevel() == wanYaoBlockData.getBlockLevel() && !hasList.contains(downBlock)) {
                return downBlock;
            }
        }
        if (wanYaoBlockData.getY() < 4) {
            WanYaoBlockData upBlock = getBlockByXY(boardData, wanYaoBlockData.getX(), wanYaoBlockData.getY() + 1);
            if (upBlock != null && upBlock.getBlockLevel() == wanYaoBlockData.getBlockLevel() && !hasList.contains(upBlock)) {
                return upBlock;
            }
        }
        return null;
    }

    /**
     * 掉落检测
     *
     * @param boardData
     * @return
     */

    public WanYaoProto.WanYaoMergeParseMsg.Builder fallCheck(Map<Integer, WanYaoBlockData> boardData) {
//        System.out.println("开始检测");
        printBoard(boardData);
        WanYaoProto.WanYaoMergeParseMsg.Builder fallMsg = WanYaoProto.WanYaoMergeParseMsg.newBuilder();
        fallMsg.setOldBoard(parseBoardMsg(boardData));
        List<Integer> disappearList = new ArrayList<>();
        boolean needFall = false;
        //检查是否有空的方块
        for (WanYaoBlockData wanYaoBlockData : boardData.values()) {
            //如果方块空了
            if (wanYaoBlockData.getBlockLevel() <= 0) {
                needFall = true;
                //删除列表新增
                disappearList.add(wanYaoBlockData.getBlockId());

                int x = wanYaoBlockData.getX();
                int y = wanYaoBlockData.getY();
                //先手动移出盘面 以免后面get错方块
                wanYaoBlockData.setX(-1);
                wanYaoBlockData.setY(-1);
                //如果方块上面还有方块
                if (y < 4) {
                    for (int i = y + 1; i < 5; i++) {
                        //拿出原本在上方的方块
                        WanYaoBlockData upBlockData = getBlockByXY(boardData, x, i);
                        //如果上面的方块不为空
                        if (upBlockData != null) {
                            //上面的方块掉落
                            upBlockData.setY(upBlockData.getY() - 1);
                        }
                    }
                }
            }
        }
//        System.out.println("移出盘面后");
        printBoard(boardData);

        for (int id : disappearList) {
//            System.out.println("disappearList id = " + id);
            //先把消失的方块从盘面移除
            boardData.remove(id);
        }

        if (needFall) {
            //填充0行到4行和0列到4列的空缺
            for (int i = 0; i < 5; i++) {
                List<WanYaoBlockData> blockDataList = getBlockByX(boardData, i);
                if (blockDataList.size() < 5) {
                    for (int j = 0; j < 5; j++) {
                        WanYaoBlockData blockData = getBlockByXY(boardData, i, j);
                        if (blockData == null) {
//                            System.out.println("x = " + i + " y = " + j + "不存在 需要填充");
                            int restoreId = disappearList.get(0);
                            disappearList.remove(0);
                            WanYaoBlockData newBlockData = WanYaoMgr.getRandomBlockByKingLevel(userData.getMonsterKingLevel(), restoreId, i, j);
                            boardData.put(newBlockData.getBlockId(), newBlockData);
//                            System.out.println("newBlockData id = " + newBlockData.getBlockId());
                        }
                    }
                }
            }
            //添加掉落信息
            fallMsg.setNewBoard(parseBoardMsg(boardData));
            return fallMsg;
        } else {
            return null;
        }

    }

    /**
     * 用xy获取方块
     *
     * @param blockDataMap
     * @param x
     * @param y
     * @return
     */


    public WanYaoBlockData getBlockByXY(Map<Integer, WanYaoBlockData> blockDataMap, int x, int y) {
        for (WanYaoBlockData blockData : blockDataMap.values()) {
            if (blockData.getX() == x && blockData.getY() == y) {
                return blockData;
            }
        }
        return null;
    }

    /**
     * 用x获取同列方块
     *
     * @param blockDataMap
     * @param x
     * @return
     */

    public List<WanYaoBlockData> getBlockByX(Map<Integer, WanYaoBlockData> blockDataMap, int x) {
        List<WanYaoBlockData> blockDataList = new ArrayList<>();
        for (WanYaoBlockData blockData : blockDataMap.values()) {
            if (blockData.getX() == x) {
                blockDataList.add(blockData);
            }
        }
        return blockDataList;
    }

    /**
     * 使用y获取同行方块
     *
     * @param blockDataMap
     * @param y
     * @return
     */

    public List<WanYaoBlockData> getBlockByY(Map<Integer, WanYaoBlockData> blockDataMap, int y) {
        List<WanYaoBlockData> blockDataList = new ArrayList<>();
        for (WanYaoBlockData blockData : blockDataMap.values()) {
            if (blockData.getY() == y) {
                blockDataList.add(blockData);
            }
        }
        return blockDataList;
    }

    /**
     * 获取空的方块
     *
     * @param id
     * @param x
     * @param y
     * @return
     */
    public WanYaoBlockData getEmptyWanYaoBlockData(int id, int x, int y) {
        WanYaoBlockData wanYaoBlockData = new WanYaoBlockData();
        wanYaoBlockData.setBlockId(id);
        wanYaoBlockData.setX(x);
        wanYaoBlockData.setY(y);
        wanYaoBlockData.setBlockLevel(0);
        return wanYaoBlockData;
    }

    /**
     * 解析方块信息
     *
     * @param wanYaoBlockData
     * @return
     */

    public WanYaoProto.WanYaoBlockMsg.Builder parseBlockMsg(WanYaoBlockData wanYaoBlockData) {
        WanYaoProto.WanYaoBlockMsg.Builder blockBuilder = WanYaoProto.WanYaoBlockMsg.newBuilder();
        blockBuilder.setId(wanYaoBlockData.getBlockId());
        blockBuilder.setLevel(wanYaoBlockData.getBlockLevel());
        blockBuilder.setX(wanYaoBlockData.getX());
        blockBuilder.setY(wanYaoBlockData.getY());
        return blockBuilder;
    }

    /**
     * 解析棋盘信息
     *
     * @param boardData
     * @return
     */

    public WanYaoProto.WanYaoBoardMsg.Builder parseBoardMsg(Map<Integer, WanYaoBlockData> boardData) {
        WanYaoProto.WanYaoBoardMsg.Builder boardBuilder = WanYaoProto.WanYaoBoardMsg.newBuilder();
        for (WanYaoBlockData wanYaoBlockData : boardData.values()) {
            WanYaoProto.WanYaoBlockMsg.Builder blockBuilder = parseBlockMsg(wanYaoBlockData);
            boardBuilder.addBlocks(blockBuilder);
        }
        return boardBuilder;

    }

    public void printBoard(Map<Integer, WanYaoBlockData> boardData) {
//        System.out.println("打印棋盘");
//
//        for (int y = 4; y >= 0 ; y--) {
//            for (int x = 0 ; x < 5;x++) {
//                WanYaoBlockData blockData = getBlockByXY(boardData, x, y);
//                if (blockData != null) {
//                    System.out.print(" "+blockData.getBlockId()+":"+blockData.getBlockLevel()+" x:" + blockData.getX() + " y:" + blockData.getY() + " ");
//                } else {
//                    System.out.print(" "+0+" "+0+" ");
//                }
//
//            }
//            System.out.println();
//        }
//        System.out.println("  ");

    }

}
